#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <stdarg.h>
#include <pthread.h>
#include <time.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex4 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex5 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex6 = PTHREAD_MUTEX_INITIALIZER;

mpf_t ak1,ak, bk, pk, sq;
mpf_t comp1, comp2, comp3;


void calcularAk(void){

	pthread_mutex_lock(&mutex1);

	mpf_ui_div(comp3, 1, sq);
	mpf_add(ak1, sq, comp3);
	mpf_div_ui(ak1, ak1, 2);

	pthread_mutex_unlock(&mutex1);	

}

void calcularTh21Fator(mpf_t *comp){

	pthread_mutex_lock(&mutex2);

	mpf_add_ui(comp1, bk, 1);
	mpf_mul(comp1, comp1, sq);

	pthread_mutex_unlock(&mutex2);	
	
}

void calcularTh22Fator(mpf_t *comp){

	pthread_mutex_lock(&mutex3);

	mpf_add(comp2, ak, bk);

	pthread_mutex_unlock(&mutex3);
	
}


void calcularTh31Fator(mpf_t *comp){
	
	pthread_mutex_lock(&mutex4);

	mpf_add_ui(comp1, ak1, 1);

	pthread_mutex_unlock(&mutex4);

}

void calcularTh33Fator(mpf_t *comp){
	

	pthread_mutex_lock(&mutex6);

	mpf_add_ui(comp2, bk, 1);

	pthread_mutex_unlock(&mutex6);

}

void calcularTh32Fator(mpf_t *comp){
	
	pthread_mutex_lock(&mutex5);

	mpf_mul(comp3, pk, bk);

	pthread_mutex_unlock(&mutex5);

}


int main(int argc, char *argv[]) {


int i;
clock_t begin, end;

pthread_t th1;
pthread_t th2;
pthread_t th3;
pthread_t th4;
pthread_t th5;
pthread_t th6;
  FILE *f = fopen("pi_borwein_par.txt","w+");

  if(f == NULL) {
    return EXIT_FAILURE;
  }


  long default_prec = 40000000;
	mpf_init2(ak, default_prec);
	mpf_init2(ak1, default_prec);
	mpf_init2(bk, default_prec);
	mpf_init2(pk, default_prec);
	mpf_init2(sq, default_prec);
	mpf_init2(comp1, default_prec);
	mpf_init2(comp2, default_prec);
	mpf_init2(comp3, default_prec);

  begin = clock();
	//iniciando a0
	mpf_sqrt_ui(ak, 2);
	
	//iniciando o b0
	mpf_set_d(bk, 0.0);

	//iniciando o p0
	mpf_add_ui(pk, ak, 2);


	for(i = 0; i < 22; i++){
		mpf_sqrt(sq, ak);


		pthread_create(&th1, NULL, (void *)calcularAk, (void*)NULL);

		pthread_create(&th2, NULL, (void *) calcularTh21Fator, (void *) (NULL));

		pthread_create(&th3, NULL, (void *)calcularTh22Fator, (void *)(NULL));

		pthread_join(th2, NULL);
		pthread_join(th3, NULL);
		pthread_join(th1, NULL);

		mpf_div(bk, comp1,comp2);

		pthread_create(&th4, NULL, (void *) calcularTh31Fator, (void *) (NULL));

		pthread_create(&th5, NULL, (void *) calcularTh32Fator, (void *) (NULL));

		pthread_create(&th6, NULL, (void *) calcularTh33Fator, (void *) (NULL));
		
		pthread_join(th4, NULL);
		pthread_join(th6, NULL);
		pthread_join(th5, NULL);

		mpf_mul(comp1, comp1, comp3);
		mpf_div(pk, comp1, comp2);
		mpf_set(ak, ak1);

    mpf_out_str(f,10,0,pk);
    fprintf(f,"\n");
}
  end = clock();

  printf("Tempo de cálculo: %lf\n",(double)(end - begin)/CLOCKS_PER_SEC);

  fclose(f);

	mpf_clear(ak);
	mpf_clear(bk);	
	mpf_clear(pk);
	mpf_clear(sq);
	mpf_clear(comp1);
	mpf_clear(comp2);
	mpf_clear(comp3);
	mpf_clear(ak1);

	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);
	pthread_mutex_destroy(&mutex3);
	pthread_mutex_destroy(&mutex4);
	pthread_mutex_destroy(&mutex5);
	pthread_mutex_destroy(&mutex6);

	pthread_exit(NULL);


return 0;
}

